import ast
import datetime
import json


from word_converter import json_to_word_converter,transform_project_outline,find_node_by_serial_path
from flask import Blueprint, request, jsonify
from services.user_service import UserService
from APP_DOC_GEN import og, cg, db
from META import settings_
from app import inject_parse,add_dir,fragments,dir_tree


user_bp = Blueprint('user_bp', __name__)


@user_bp.route('/api/users', methods=['POST'])
def create_user():
    """
    处理创建用户的POST请求

    验证请求数据，调用服务层保存用户，并返回响应

    Returns:
        JSON响应，包含用户数据或错误信息
    """
    user_data = request.get_json()
    if not user_data:
        return jsonify({"error": "请求数据为空"}), 400
    converted_user_data = {
        'style_id': user_data.get('styleId'),
        'live': user_data.get('live'),
        'update_by': user_data.get('updateBy')  # 假设前端也使用驼峰命名法
    }
    #校验
    # required_fields = ['style_id', 'live']
    # for field in required_fields:
    #     if field not in user_data:
    #         return jsonify({"error": f"缺少字段{field}"}), 400

    try:
        user_service = UserService()
        user = user_service.save_user(converted_user_data)
        return jsonify({
            "id": user.style_id,
            "name": user.live,
            "email": user.update_by
        }), 201
    except Exception as e:
        return jsonify({"error": str(e)}), 500


@user_bp.route('/api/getuser', methods=['post'])
def get_user():
    page = request.args.get('page', 1, type=int)
    page_size = request.args.get('pageSize', 10, type=int)

    style_id = request.args.get('styleId', type=int)
    live = request.args.get('live', type=lambda v: v.lower() == 'true')
    user_service = UserService()

    users, total = user_service.get_users_by_style_and_live(
        style_id=style_id,
        live=live,
        page=page,
        page_size=page_size
    )
    return jsonify({
        "data": [user.to_json() for user in users],
        "total": total,
        "page": page,
        "pageSize": page_size,
        "totalPages": (total + page_size - 1)

    })


@user_bp.route('/api/gettitle', methods=['post'])
def gettitle():
    try:
        request_data = request.get_json()
        if 'overview' not in request_data:
            return {"error": "Missing 'content' field in request"}, 400
        if 'head' not in request_data:
            return {"error": "Missing 'head' field in request"}, 400
        jstitle = {
            "title": request_data['head'],
            "content": request_data['overview']
        }
    except Exception as e:
        return {"error": f"Invalid JSON request: {str(e)}"}, 400
    try:
        res_data = og.gen_root_titles(jstitle, "ds_api")
        db.save_record(res_data)
        res_json = json.dumps(res_data, indent=4, ensure_ascii=False)
        return res_json
    except Exception as e:
        return {"error": f"Processing error: {str(e)}"}, 500

@user_bp.route('/api/detailed', methods=['post'])
def detailed_title():
    request_data = request.get_json()
    if 'bid' not in request_data:
        return {"error": "参数 'bid' 是必须提交的"}, 400
    if 'thoughts' not in request_data:
        return {"error": "参数 'thoughts' 是必须提交的"}, 400
    try:
        res_data = og.gen_detailed_titles(request_data)
        return json.dumps(res_data, indent=4, ensure_ascii=False)
    except Exception as e:
        return {"error": f"Processing error: {str(e)}"}, 500

#根据bid和version获取标书生成的正文
@user_bp.route("/api/gencontent", methods=['post'])
def gen_content():
    request_data = request.get_json()
    if 'bid' not in request_data:
        return {"error": "参数 'bid' 时必须提交的"}, 400
    if 'version' not in request_data:
        return {"error": " 参数 'version' 是必须提交的 "}, 400
    try:
        res_data = cg.gen_contents(request_data,"ds_api",limit=30, mode='naive')
        return json.dumps(res_data, indent=4, ensure_ascii=False)
    except Exception as e:
        return {"error": f"Processing error: {str(e)}"}, 500

#根据bid下载已经生成的标书
@user_bp.route("/api/downDocByBid", methods=['post'])
def download_doc():
    request_data = request.get_json()
    if 'bid' not in request_data:
        return {"error": "参数 'bid' 时必须提交的"}, 400
    try:
        db_bid = db.search_record(request_data['bid'])
        db_data = db_bid['data'][0]['catalog']

        output_filename = r"E:\project\项目概述文档.docx"
        json_to_word_converter(db_data, output_filename)
        db_data = {
            "code":0,
            "down_url": "http://",
            "date": datetime.datetime
        }
        return json.dumps(db_data, indent=4, ensure_ascii=False)
    except Exception as e:
        return {"error": f"Processing error: {str(e)}"}, 500


#根据bid获取已经生成的完整目录
@user_bp.route("/api/getCatalogByBid", methods=['post'])
def catalog_by_bid():
    request_data = request.get_json()
    if 'bid' not in request_data:
        return {"error": "参数 'bid' 时必须提交的"}, 400
    db_bid = db.search_record(request_data['bid'])
    db_data = db_bid['data'][0]['catalog']
    catalog = transform_project_outline(db_data)
    res_data = {
        "title":db_bid.get('title',"标题错误"),
        "catalog":catalog,
        "words":db_bid.get('words',"100000"),
        "pages":db_bid.get('pages',"200")
    }
    return json.dumps(res_data, ensure_ascii=False, indent=4)

#根据bid和层级获得节点内容
@user_bp.route("/api/getChildernBidserial", methods=['post'])
def get_childern_bidserial():
    request_data = request.get_json()
    if 'bid' not in request_data:
        return {"error": "参数 'bid' 时必须提交的"}, 400
    if 'pathBySerial' not in request_data:
        return { "error": "参数 pathBySerial 是必须提交的"}
    db_bid = db.search_record(request_data['bid'])
    db_data = db_bid['data'][0]['catalog']
    if validate_path_payload(request_data.get('pathBySerial')):
        res_data = find_node_by_serial_path(db_data,request_data.get('pathBySerial'))
        return json.dumps(res_data, ensure_ascii=False, indent=4)
    else:
        return { "error": "参数 pathBySerial 不正确"}
#根据用户信息创建知识库
@user_bp.route("/api/createknowledge",methods=['post'])
def createknowledge():
    request_data = request.get_json()
    if 'user' not in request_data:
        return {"error": "参数 'bid' 时必须提交的"}, 400
    res_data = settings_(request_data.get('user'))
    res_data = {
        "kbpath":res_data[1],
        "successs":"ok"
    }
    return res_data

#根据用户增加知识库内容
@user_bp.route('/api/inject_parse', methods=['POST'])
def upknowledge():
    request_data = request
    return decode_unicode_escapes(inject_parse(request_data))

# #创建新的根目录
# @user_bp.route('/api/createfolder',methods=['post'])
# def createfolder():
#     return add_dir(request)

#获取知识库详情
@user_bp.route('/api/fragments',methods=['post'])
def ufragments():
    request_data = request.get_json()
    if 'dir_path' not in request_data:
        return {"error": "参数 'dir_path' 时必须提交的"}, 400
    if 'user' not in request_data:
        return {"error": "参数 'user' 时必须提交的"}, 400
    if 'KB_PATH' not in request_data:
        return {"error": "参数 'KB_PATH' 时必须提交的"}, 400
    return fragments(request_data)

@user_bp.route('/api/dirTree',methods=['post'])
def dirTree():
    request_data = request.get_json()
    if 'user' not in request_data:
        return {"error": "参数 'user' 时必须提交的"}, 400
    return dir_tree(request)
"""
增加Unicode解码
"""
def decode_unicode_escapes(data):
    if isinstance(data, dict):
        return {k: decode_unicode_escapes(v) for k, v in data.items()}
    elif isinstance(data, list):
        return [decode_unicode_escapes(item) for item in data]
    elif isinstance(data, str):
        # 安全解码Unicode转义序列
        return ast.literal_eval(f'"{data}"')
    else:
        return data

#目录层级参数校验
def validate_path_payload(payload):
    if not isinstance(payload, dict):
        return False, "对象必须为json."
    if len(payload) != 1:
        return False, "请求格式无效，至少包含一个key."
    expected_key = "path_by_serial"

    if expected_key not in payload:
        return False, f"格式无效: Expected key '{expected_key}' 找不到"

    path_list = payload[expected_key]
    #  检查key是否list
    if not isinstance(path_list, list):
        return False, f"Invalid value for '{expected_key}': Must be a list."

    # 6.检查是否为空，至少有一个节点
    if not path_list:
        return False, f"Invalid value for '{expected_key}': 不能提交空的listy."

    # 7. 检查列表中是是否都是正整数
    for i, item in enumerate(path_list):
        if not isinstance(item, int) or item <= 0:
            return False, f"Invalid value for '{expected_key}': 所有元素都必须是正整数。在索引处发现无效元素 {i}."

    # 所有检查都通过了，则返回数据有效
    return True, path_list
